﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using Microsoft.Practices.ServiceLocation;

namespace DomainModel
{
    /// <summary>
    /// Représente un Signalement
    /// </summary>
    public class Signalement : Entity
    {
        public ObjetPatrimonial ObjetPatrimonial { get; private set; }

        public Panne Panne { get; private set; }

        public DateTime BeginDate { get; private set; }

        public DateTime MaxRepairDate { get; private set; }

        [StringLength(50, ErrorMessage = "Le commentaire ne doit pas dépasser les 50 caractères")]
        public string Comments { get; private set; }

        public bool IsUrgent { get; private set; }

        public bool IsTerminated { get; private set; }

        private Signalement()
        {
        }

        private bool IsValidRegardingContract()
        {
            return MaxRepairDate > DateTime.Now;
        }

        public void Terminate()
        {
            ObjetPatrimonial.State = ObjetPatrimonialState.FullyOperational;
            IsTerminated = true;
        }

        // Utilisation de "Factory method" pattern

        public static Signalement CreateSignalementWithAutomaticDelay(int objetPatrimonialId, int panneId, DateTime beginDate, string comments)
        {
            var objetPatrimonialRepository = ServiceLocator.Current.GetInstance<IObjetPatrimonialRepository>();
            var panneRepository = ServiceLocator.Current.GetInstance<IPanneRepository>();

            var objetPatrimonial = objetPatrimonialRepository.Find(objetPatrimonialId);
            var panne = panneRepository.Find(panneId);

            if (objetPatrimonial != null && panne != null)
            {
                var delayCalculator = new DelayCalculator();
                var signalement = new Signalement { ObjetPatrimonial = objetPatrimonial, Panne = panne, BeginDate = beginDate, Comments = comments };

                if (panne.Severity == PanneSeverity.Serious)
                {
                    signalement.IsUrgent = true;
                    delayCalculator.AssignCalculatingStrategy(new UrgentDelayCalculating(objetPatrimonial, panne));
                    signalement.MaxRepairDate = signalement.BeginDate.Add(delayCalculator.CalculateMaxRepairDelay());
                }
                else
                {
                    signalement.IsUrgent = false;
                    delayCalculator.AssignCalculatingStrategy(new NormalDelayCalculating(panne));
                    signalement.MaxRepairDate = signalement.BeginDate.Add(delayCalculator.CalculateMaxRepairDelay());
                }

                return signalement.IsValidRegardingContract() ? signalement : null;
            }

            return null;
        }

        public static Signalement CreateSignalement(ObjetPatrimonial objetPatrimonial, Panne panne, 
                                                    DateTime beginDate, string comments, DateTime maxRepairDate, bool isUrgent)
        {
            var signalement = new Signalement
                                  {
                                      ObjetPatrimonial = objetPatrimonial,
                                      Panne = panne,
                                      BeginDate = beginDate,
                                      Comments = comments,
                                      MaxRepairDate = maxRepairDate,
                                      IsUrgent = isUrgent,
                                      IsTerminated = false
                                  };

            return signalement;
        }
    }
}
